package test_pkg

import (
	"fmt"
	"sort"
)

//map 引用类型
//声明方式 var map1 map[keytype]valuetype
// 在声明的时候不需要知道 map 的长度，map 是可以动态增长的。未初始化的 map 的值是 nil
// map 传递给函数的代价很小：在 32 位机器上占 4 个字节，64 位机器上占 8 个字节，无论实际上存储了多少数据。
// 通过 key 在 map 中寻找值是很快的，比线性查找快得多，但是仍然比从数组和切片的索引中直接读取要慢 100 倍；
// 所以如果你很在乎性能的话还是建议用切片来解决问题
// map 也可以用函数作为自己的值

func Test_map() {
	//不要使用 new，永远用 make 来构造 map
	var mapLit map[string]int
	//var mapCreated map[string]float32
	var mapAssigned map[string]int

	mapLit = map[string]int{"one": 1, "two": 2}
	mapCreated := make(map[string]float32)
	mapAssigned = mapLit

	mapCreated["key1"] = 4.5
	mapCreated["key2"] = 3.14159
	mapAssigned["two"] = 3

	fmt.Printf("Map literal at \"one\" is: %d\n", mapLit["one"])
	fmt.Printf("Map created at \"key2\" is: %f\n", mapCreated["key2"])
	fmt.Printf("Map assigned at \"two\" is: %d\n", mapAssigned["two"])
	fmt.Printf("Map literal at \"ten\" is: %d\n", mapLit["ten"])

	//map 的值可以是任意类型
	mp := map[int]func() int{
		1: func() int { return 1 },
		2: func() int { return 2 },
		3: func() int { return 3 },
	}

	fmt.Println(mp)

	fmt.Println("------ 判断值是否存在----------")
	_, isPresent := mapCreated["key1"]
	_, isPresent2 := mapCreated["key"]
	fmt.Printf("isPresent: %v\n", isPresent)
	fmt.Printf("isPresent2: %v\n", isPresent2)

	fmt.Println("-----删除--------")
	fmt.Println(mapCreated)
	delete(mapCreated, "key1") //key 不存在 不会产生错误
	fmt.Println(mapCreated)
}

// map 类型的切片
func Map_slice() {
	//声明切片
	slice := make([]map[int]int, 2)
	slice2 := make([]map[int]int, 2)

	for i, _ := range slice {
		slice[i] = make(map[int]int, 1)
		slice[i][0] = 2
	}

	fmt.Printf("Version A: Value of items: %v\n", slice)

	for _, v := range slice2 {
		v = make(map[int]int, 1)
		v[0] = 3
		fmt.Println(v)
	}

	// B 版本中获得的项只是 map 值的一个拷贝而已，所以真正的 map 元素没有得到初始化
	fmt.Printf("Version B: Value of items: %v\n", slice2)
}

// map 默认是无序的， 可将其copy 到切片，通过切片排序
func Map_sort() {
	barVal := map[string]int{
		"alpha": 34, "bravo": 56, "charlie": 23,
		"delta": 87, "echo": 56, "foxtrot": 12,
		"golf": 34, "hotel": 16, "indio": 87,
		"juliet": 65, "kili": 43, "lima": 98,
	}

	//切片
	var vals = make([]int, len(barVal))    //按值排序
	var keys = make([]string, len(barVal)) //按索引排序
	i := 0
	for k, v := range barVal {
		keys[i] = k
		vals[i] = v
		i++
	}

	sort.Strings(keys)
	sort.Ints(vals)

	for _, k := range keys {
		fmt.Printf("Key: %v, Value: %v / ", k, barVal[k])
	}

}
